{
 "cells": [
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-01-18T13:16:04.225455Z",
     "start_time": "2025-01-18T13:16:04.219047Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "\n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)  #设备是cuda:0，即GPU，如果没有GPU则是cpu\n",
    "\n",
    "seed = 42\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.0\n",
      "torch 2.5.1+cpu\n",
      "cpu\n"
     ]
    }
   ],
   "execution_count": 37
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 数据准备",
   "id": "1073bc64c567ba13"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:16:04.363525Z",
     "start_time": "2025-01-18T13:16:04.317479Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torch.utils.data import random_split\n",
    "\n",
    "# 训练集\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "# 测试集\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 这里用 random_split 按照 11 : 1 的比例来划分数据集\n",
    "train_ds, val_ds = random_split(train_ds, [55000, 5000], torch.Generator().manual_seed(seed))\n",
    "\n",
    "\n"
   ],
   "id": "55788f25672e1ebe",
   "outputs": [],
   "execution_count": 38
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "",
   "id": "4fffd32f199496a1"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:16:11.042028Z",
     "start_time": "2025-01-18T13:16:04.372528Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from torchvision.transforms import Normalize\n",
    "\n",
    "\n",
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img.mean(dim=(1, 2))\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "\n",
    "_mean, _std = cal_mean_std(train_ds)\n",
    "transforms = nn.Sequential(\n",
    "    Normalize(mean=_mean, std=_std),\n",
    ")\n",
    "\n",
    "_mean, _std"
   ],
   "id": "f17a4198ee382763",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([0.2856]), tensor([0.3202]))"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 39
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:16:11.047885Z",
     "start_time": "2025-01-18T13:16:11.043031Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 从数据集到dataloader\n",
    "batch_size = 32\n",
    "# num_workers 多线程加载数据，提高效率\n",
    "train_loader = torch.utils.data.DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=2)\n",
    "val_loader = torch.utils.data.DataLoader(val_ds, batch_size=batch_size, shuffle=False, num_workers=2)\n",
    "test_loader = torch.utils.data.DataLoader(test_ds, batch_size=batch_size, shuffle=False, num_workers=2)"
   ],
   "id": "ccdf8026c7024c31",
   "outputs": [],
   "execution_count": 40
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 定义模型",
   "id": "b5e4f17ae389c008"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:16:11.064434Z",
     "start_time": "2025-01-18T13:16:11.048899Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class CNN(nn.Module):\n",
    "    def __init__(self, activation=\"relu\"):\n",
    "        super(CNN, self).__init__()\n",
    "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
    "        self.flattener = nn.Flatten()  # 展平层\n",
    "        # 卷积层\n",
    "        # nn.Conv2d:这是 PyTorch 中的二维卷积层，用于处理二维输入数据（如图像）。\n",
    "        # in_channels=1：输入数据的通道数。\n",
    "        #               对于灰度图像，通道数为 1；对于 RGB 图像，通道数为 3\n",
    "        # out_channels=32：输出数据的通道数，即卷积核的数量。\n",
    "        #                 每个卷积核会提取输入数据的不同特征\n",
    "        # kernel_size=3：卷积核的大小，通常是一个正方形。\n",
    "        #               kernel_size=3 表示卷积核的大小为 3x3。\n",
    "        # padding=1：在输入数据的边缘填充 0 的层数。\n",
    "        #              对于卷积层，padding=1 表示在输入数据的每一边填充 1 层 0，确保输出数据的空间尺寸与输入数据相同。\n",
    "        #输入x(32,1,28,28) 输出x(32,32,28,28)        \n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv4 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv5 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.conv6 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=1)\n",
    "        # 池化层\n",
    "        # nn.MaxPool2d:这是 PyTorch 中的最大池化层，用于对输入数据进行降采样。\n",
    "        # kernel_size=2：池化核的大小，通常是一个正方形。\n",
    "        self.pool = nn.MaxPool2d(2, 2)  #池化核大小为2（2*2），步长为2\n",
    "        # 全连接层\n",
    "        # (32,128,3,3)->(32,128*3*3)\n",
    "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
    "        self.fc2 = nn.Linear(128, 10)  # 输出层，10个类别 #输出尺寸（32,10）\n",
    "\n",
    "        self.init_weights()  # 初始化权重\n",
    "\n",
    "    def init_weights(self):  # 初始化权重\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "\n",
    "    def forward(self, x):\n",
    "        act = self.activation\n",
    "        #          conv1          conv2         pool  \n",
    "        # 32*1*28*28 -> 32*32*28*28-> 32*32*28*28->32*32*14*14\n",
    "        x = self.pool(act(self.conv2(act(self.conv1(x)))))\n",
    "        # print(x.shape)\n",
    "        #           conv3          conv4         pool  \n",
    "        # 32*32*14*14 -> 32*64*14*14 -> 32*64*14*14 -> 32*64*7*7\n",
    "        x = self.pool(act(self.conv4(act(self.conv3(x)))))\n",
    "        # print(x.shape)\n",
    "        #           conv5          conv6         pool  \n",
    "        # 32*64*7*7 -> 32*128*7*7 -> 32*128*7*7 -> 32*128*3*3\n",
    "        x = self.pool(act(self.conv6(act(self.conv5(x)))))\n",
    "        # print(x.shape)\n",
    "\n",
    "        # 32*128*3*3 ->32*(128*3*3)\n",
    "        x = self.flattener(x)  #展平\n",
    "        # 32*(128*3*3)->32*128\n",
    "        x = act(self.fc1(x))\n",
    "        # 32*128->32*10\n",
    "        x = self.fc2(x)\n",
    "        return x\n",
    "    \n",
    "\n",
    "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
    "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\") # 打印模型的参数信息"
   ],
   "id": "d3016623476b4fd4",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1.weight\tparamerters num: 288\n",
      "conv1.bias\tparamerters num: 32\n",
      "conv2.weight\tparamerters num: 9216\n",
      "conv2.bias\tparamerters num: 32\n",
      "conv3.weight\tparamerters num: 18432\n",
      "conv3.bias\tparamerters num: 64\n",
      "conv4.weight\tparamerters num: 36864\n",
      "conv4.bias\tparamerters num: 64\n",
      "conv5.weight\tparamerters num: 73728\n",
      "conv5.bias\tparamerters num: 128\n",
      "conv6.weight\tparamerters num: 147456\n",
      "conv6.bias\tparamerters num: 128\n",
      "fc1.weight\tparamerters num: 147456\n",
      "fc1.bias\tparamerters num: 128\n",
      "fc2.weight\tparamerters num: 1280\n",
      "fc2.bias\tparamerters num: 10\n"
     ]
    }
   ],
   "execution_count": 41
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 训练模型",
   "id": "8fb5dfcd77513c03"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:16:11.070623Z",
     "start_time": "2025-01-18T13:16:11.065440Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "\n",
    "@torch.no_grad()  # 装饰器，禁止梯度计算\n",
    "def evaluate(model, data_loader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in data_loader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "\n",
    "        # 前向传播\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)  # 验证集损失\n",
    "        # tensor.item() 获取tensor的数值，loss是只有一个元素的tensor\n",
    "        loss_list.append(loss.item())\n",
    "\n",
    "        # 预测\n",
    "        preds = logits.argmax(axis=-1)  # 预测类别\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())  # tensor转numpy，再转list\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "\n",
    "    acc = accuracy_score(label_list, pred_list)  # 计算准确率\n",
    "    return np.mean(loss_list), acc  # # 返回验证集平均损失和准确率\n"
   ],
   "id": "24550945260b9755",
   "outputs": [],
   "execution_count": 42
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## Save Best Model",
   "id": "6fd06a23a5bccc23"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:16:11.077857Z",
     "start_time": "2025-01-18T13:16:11.071626Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=500, save_best_only=True):\n",
    "        self.save_dir = save_dir  # 保存路径\n",
    "        self.save_step = save_step  # 保存步数\n",
    "        self.save_best_only = save_best_only  # 是否只保存最好的模型\n",
    "        self.best_metric = -1  # 最好的指标，指标不可能为负数，所以初始化为-1\n",
    "        # 创建保存路径\n",
    "        if not os.path.exists(self.save_dir):  # 如果不存在保存路径，则创建\n",
    "            os.makedirs(self.save_dir)\n",
    "\n",
    "    # 对象被调用时：当你将对象像函数一样调用时，Python 会自动调用 __call__ 方法。\n",
    "    # state_dict() 返回模型参数的字典，包括模型参数和优化器参数\n",
    "    # metric 是指标，可以是验证集的准确率，也可以是其他指标\n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return  # 不是保存步数，则直接返回\n",
    "\n",
    "        if self.save_best_only:\n",
    "            assert metric is not None  # 必须传入metric\n",
    "            if metric >= self.best_metric:  # 如果当前指标大于最好的指标\n",
    "                # save checkpoint\n",
    "                # 保存最好的模型，覆盖之前的模型，不保存step，只保存state_dict，即模型参数，不保存优化器参数\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"01_cnn_best.ckpt\"))\n",
    "                self.best_metric = metric  # 更新最好的指标\n",
    "        else:\n",
    "            # 保存模型\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "            # 保存每个step的模型，不覆盖之前的模型，保存step，保存state_dict，即模型参数，不保存优化器参数\n"
   ],
   "id": "e93aec97aec45c4e",
   "outputs": [],
   "execution_count": 43
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## Early Stopping",
   "id": "3f9a004729448217"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:16:11.083172Z",
     "start_time": "2025-01-18T13:16:11.078871Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        self.patience = patience  # 多少个step没有提升就停止训练\n",
    "        self.min_delta = min_delta  # 最小的提升幅度\n",
    "        self.best_metric = -1  # 记录的最好的指标\n",
    "        self.counter = 0  # 计数器，记录连续多少个step没有提升\n",
    "\n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:  # 如果指标提升了\n",
    "            self.best_metric = metric  # 更新最好的指标\n",
    "            self.counter = 0  # 计数器清零\n",
    "        else:\n",
    "            self.counter += 1  # 计数器加一\n",
    "\n",
    "    @property  # 使用@property装饰器，使得 对象.early_stop可以调用，不需要()\n",
    "    def early_stop(self):\n",
    "        # 如果计数器大于等于patience，则返回True，停止训练\n",
    "        return self.counter >= self.patience\n"
   ],
   "id": "d8fdc303a4d27c00",
   "outputs": [],
   "execution_count": 44
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 训练",
   "id": "b56dab87e8ff6485"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:16:11.091440Z",
     "start_time": "2025-01-18T13:16:11.084177Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def training(model,\n",
    "             train_loader,\n",
    "             val_loader,\n",
    "             epoch,\n",
    "             loss_fct,\n",
    "             optimizer,\n",
    "             save_ckpt_callback=None,\n",
    "             early_stop_callback=None,\n",
    "             eval_step=500,\n",
    "             ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "\n",
    "    global_step = 0  # 全局步数\n",
    "    model.train()  # 训练模式\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "\n",
    "                # 前向传播\n",
    "                logits = model(datas)\n",
    "                loss = loss_fct(logits, labels)  # 训练集损失\n",
    "                preds = logits.argmax(axis=-1)  # 预测类别\n",
    "\n",
    "                # 反向传播\n",
    "                optimizer.zero_grad()  # 梯度清零\n",
    "                loss.backward()  # 反向传播\n",
    "                optimizer.step()  # 优化器更新参数\n",
    "\n",
    "                # 计算准确率\n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())\n",
    "                loss = loss.cpu().item()\n",
    "\n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss,\n",
    "                    \"acc\": acc,\n",
    "                    \"step\": global_step\n",
    "                })\n",
    "\n",
    "                # 评估\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()  # 评估模式\n",
    "                    # 验证集损失和准确率\n",
    "                    val_loss, val_acc = evaluate(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss,\n",
    "                        \"acc\": val_acc,\n",
    "                        \"step\": global_step\n",
    "                    })\n",
    "                    model.train()  # 训练模式\n",
    "\n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        # model.state_dict() 返回模型参数的字典，包括模型参数和优化器参数\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), val_acc)\n",
    "                        # 保存最好的模型，覆盖之前的模型，保存step，保存state_dict,通过metric判断是否保存最好的模型\n",
    "\n",
    "                    # 3. 早停 early stopping\n",
    "                    if early_stop_callback is not None:\n",
    "                        # 验证集准确率不再提升，则停止训练\n",
    "                        early_stop_callback(val_acc)\n",
    "                        # 验证集准确率不再提升，则停止训练\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict  # 早停，返回记录字典 record_dict\n",
    "\n",
    "                # 更新进度条和全局步数\n",
    "                pbar.update(1)  # 更新进度条\n",
    "                global_step += 1  # 全局步数加一\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "\n",
    "    return record_dict  # 训练结束，返回记录字典 record_dict\n"
   ],
   "id": "2602ccd3cb633f69",
   "outputs": [],
   "execution_count": 45
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "",
   "id": "d111e077fd6e015"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:16:11.101625Z",
     "start_time": "2025-01-18T13:16:11.092444Z"
    }
   },
   "cell_type": "code",
   "source": [
    "epoch = 100\n",
    "\n",
    "activation = \"relu\"  # 激活函数\n",
    "model = CNN(activation)  # 定义模型\n",
    "\n",
    "# 1. 定义损失函数 采用MSE损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "\n",
    "# 2. 定义优化器 采用SGD优化器\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 3.save model checkpoint\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(save_dir=\"checkpoints\", save_step=500, save_best_only=True)\n",
    "\n",
    "# 4. early stopping\n",
    "early_stop_callback = EarlyStopCallback(patience=10, min_delta=0.01)"
   ],
   "id": "8b42caff09582576",
   "outputs": [],
   "execution_count": 46
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:35:05.496123Z",
     "start_time": "2025-01-18T13:16:11.102629Z"
    }
   },
   "cell_type": "code",
   "source": [
    "model = model.to(device)  # 将模型移到GPU上\n",
    "\n",
    "# 训练过程\n",
    "record_dict = training(\n",
    "    model,\n",
    "    train_loader,\n",
    "    val_loader,\n",
    "    epoch,\n",
    "    loss_fct,\n",
    "    optimizer,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=1000\n",
    ")"
   ],
   "id": "1b4d7f1cfe612c71",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/171900 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "02175835374e4035aa38836de0df1f7b"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Early stop at epoch 15 / global_step 27000\n"
     ]
    }
   ],
   "execution_count": 47
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:35:05.682201Z",
     "start_time": "2025-01-18T13:35:05.500131Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def plot_record_curves(record_dict, sample_step=500):\n",
    "    # .set_index(\"step\") 将 step 列设置为 DataFrame 的索引\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    last_step = train_df.index[-1]  # 最后一步的步数\n",
    "\n",
    "    print(train_df)\n",
    "    print(val_df)\n",
    "\n",
    "    # 画图 \n",
    "    fig_num = len(train_df.columns)  # 画两张图,分别是损失和准确率\n",
    "\n",
    "    # plt.subplots：用于创建一个包含多个子图的图形窗口。\n",
    "    # 1：表示子图的行数为 1。\n",
    "    # fig_num：表示子图的列数，即子图的数量。\n",
    "    # figsize=(5 * fig_num, 5)：设置整个图形窗口的大小，宽度为 5 * fig_num，高度为 5。\n",
    "    # fig：返回的图形对象（Figure），用于操作整个图形窗口。\n",
    "    # axs：返回的子图对象（Axes 或 Axes 数组），用于操作每个子图。\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):\n",
    "        # train_df.index 是 x 轴数据（通常是 step）。\n",
    "        # train_df[item] 是 y 轴数据（当前指标的值）。\n",
    "        axs[idx].plot(train_df.index, train_df[item], label=\"train:\" + item)\n",
    "        # val_df.index 是 x 轴数据。\n",
    "        # val_df[item] 是 y 轴数据。\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=\"val:\" + item)\n",
    "        axs[idx].grid()  # 显示网格\n",
    "        axs[idx].legend()  # 显示图例\n",
    "        axs[idx].set_xticks(range(0, train_df.index[-1], 5000))  # 设置x轴刻度\n",
    "        axs[idx].set_xticklabels(map(lambda x: f\"{x // 1000}k\", range(0, last_step + 1, 5000)))  # 设置x轴标签\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "plot_record_curves(record_dict)"
   ],
   "id": "de28437c6058f608",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "           loss      acc\n",
      "step                    \n",
      "0      2.305110  0.06250\n",
      "500    0.946051  0.59375\n",
      "1000   0.502573  0.84375\n",
      "1500   0.727404  0.71875\n",
      "2000   0.393238  0.84375\n",
      "2500   0.607218  0.75000\n",
      "3000   0.276830  0.87500\n",
      "3500   0.389660  0.87500\n",
      "4000   0.515788  0.75000\n",
      "4500   0.336779  0.87500\n",
      "5000   0.364341  0.87500\n",
      "5500   0.612487  0.84375\n",
      "6000   0.297239  0.87500\n",
      "6500   0.260458  0.87500\n",
      "7000   0.222391  0.90625\n",
      "7500   0.353688  0.87500\n",
      "8000   0.103672  0.93750\n",
      "8500   0.420327  0.75000\n",
      "9000   0.427414  0.78125\n",
      "9500   0.286277  0.87500\n",
      "10000  0.088387  0.96875\n",
      "10500  0.250744  0.87500\n",
      "11000  0.328438  0.84375\n",
      "11500  0.268164  0.90625\n",
      "12000  0.121048  0.93750\n",
      "12500  0.180543  0.96875\n",
      "13000  0.132313  0.93750\n",
      "13500  0.134148  0.96875\n",
      "14000  0.165535  0.93750\n",
      "14500  0.272393  0.90625\n",
      "15000  0.411573  0.81250\n",
      "15500  0.187117  0.90625\n",
      "16000  0.623047  0.84375\n",
      "16500  0.116996  0.96875\n",
      "17000  0.354845  0.84375\n",
      "17500  0.088839  0.96875\n",
      "18000  0.057284  1.00000\n",
      "18500  0.383659  0.93750\n",
      "19000  0.155266  0.96875\n",
      "19500  0.080494  0.96875\n",
      "20000  0.450682  0.90625\n",
      "20500  0.209833  0.90625\n",
      "21000  0.177877  0.96875\n",
      "21500  0.111706  0.96875\n",
      "22000  0.187321  0.93750\n",
      "22500  0.063599  0.96875\n",
      "23000  0.184124  0.93750\n",
      "23500  0.146401  0.96875\n",
      "24000  0.116004  0.93750\n",
      "24500  0.342343  0.87500\n",
      "25000  0.292482  0.93750\n",
      "25500  0.204061  0.87500\n",
      "26000  0.133449  0.93750\n",
      "26500  0.237920  0.90625\n",
      "27000  0.088726  0.93750\n",
      "           loss     acc\n",
      "step                   \n",
      "0      2.303428  0.1188\n",
      "1000   0.608030  0.7758\n",
      "2000   0.485345  0.8296\n",
      "3000   0.430305  0.8426\n",
      "4000   0.411063  0.8464\n",
      "5000   0.371665  0.8640\n",
      "6000   0.363512  0.8686\n",
      "7000   0.340860  0.8766\n",
      "8000   0.326779  0.8810\n",
      "9000   0.322007  0.8852\n",
      "10000  0.309575  0.8882\n",
      "11000  0.305484  0.8852\n",
      "12000  0.302496  0.8870\n",
      "13000  0.306339  0.8898\n",
      "14000  0.284366  0.8978\n",
      "15000  0.312216  0.8850\n",
      "16000  0.277455  0.8954\n",
      "17000  0.276534  0.9002\n",
      "18000  0.290862  0.8978\n",
      "19000  0.282188  0.8954\n",
      "20000  0.279046  0.8984\n",
      "21000  0.273572  0.8992\n",
      "22000  0.295355  0.8944\n",
      "23000  0.284048  0.9018\n",
      "24000  0.287188  0.8984\n",
      "25000  0.270653  0.9082\n",
      "26000  0.292074  0.9018\n",
      "27000  0.266588  0.9082\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 48
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:35:05.688270Z",
     "start_time": "2025-01-18T13:35:05.682720Z"
    }
   },
   "cell_type": "code",
   "source": "record_dict[\"train\"][-5:]",
   "id": "775b113bb78383fa",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'loss': 0.030851783230900764, 'acc': 1.0, 'step': 26996},\n",
       " {'loss': 0.1740381270647049, 'acc': 0.90625, 'step': 26997},\n",
       " {'loss': 0.06338875740766525, 'acc': 1.0, 'step': 26998},\n",
       " {'loss': 0.26900723576545715, 'acc': 0.875, 'step': 26999},\n",
       " {'loss': 0.08872587233781815, 'acc': 0.9375, 'step': 27000}]"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 49
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:35:05.694227Z",
     "start_time": "2025-01-18T13:35:05.688270Z"
    }
   },
   "cell_type": "code",
   "source": "record_dict[\"val\"][-10:]",
   "id": "dbb21c010aaef95e",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'loss': 0.2908616360680313, 'acc': 0.8978, 'step': 18000},\n",
       " {'loss': 0.2821880330088412, 'acc': 0.8954, 'step': 19000},\n",
       " {'loss': 0.27904601821047104, 'acc': 0.8984, 'step': 20000},\n",
       " {'loss': 0.27357165997100485, 'acc': 0.8992, 'step': 21000},\n",
       " {'loss': 0.2953554866657515, 'acc': 0.8944, 'step': 22000},\n",
       " {'loss': 0.2840478973949601, 'acc': 0.9018, 'step': 23000},\n",
       " {'loss': 0.2871881416008161, 'acc': 0.8984, 'step': 24000},\n",
       " {'loss': 0.27065306747699996, 'acc': 0.9082, 'step': 25000},\n",
       " {'loss': 0.2920737573936297, 'acc': 0.9018, 'step': 26000},\n",
       " {'loss': 0.26658821945926947, 'acc': 0.9082, 'step': 27000}]"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 50
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 评估以及上线",
   "id": "1fa2f200745f7b63"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:35:05.703512Z",
     "start_time": "2025-01-18T13:35:05.694227Z"
    }
   },
   "cell_type": "code",
   "source": [
    "model = CNN(activation)  #上线时加载模型\n",
    "model = model.to(device)  # 将模型移到GPU上"
   ],
   "id": "b106406c03208c15",
   "outputs": [],
   "execution_count": 51
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-18T13:38:31.377165Z",
     "start_time": "2025-01-18T13:38:22.633560Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 加载最好的模型\n",
    "# torch.load：加载保存的模型权重或整个模型。\n",
    "# \"checkpoints/best.ckpt\"：模型权重文件路径。\n",
    "# weights_only=True：仅加载模型的权重，而不是整个模型（包括结构和参数）。这是 PyTorch 2.1 引入的新特性，用于增强安全性。\n",
    "# map_location=device：将模型加载到当前设备（GPU或CPU）。\n",
    "model.load_state_dict(torch.load(\"checkpoints/01_cnn_best.ckpt\", weights_only=True, map_location=device))  # 加载最好的模型\n",
    "\n",
    "model.eval()  # 评估模式\n",
    "loss, acc = evaluate(model, test_loader, loss_fct)\n",
    "print(f\"Test loss: {loss:.4f}, Test acc: {acc:.4f}\")"
   ],
   "id": "26cdacda63d5388e",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test loss: 0.2681, Test acc: 0.9063\n"
     ]
    }
   ],
   "execution_count": 53
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
